﻿#include <stdio.h>

#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

#include "opencv2/opencv.hpp"


using namespace cv;
using namespace std;

//  [11/13/2013 yy] block start
#include "Recognition.h"
//  [11/13/2013 yy] block end
//////////////////////////////////////////////////////////////////////////

static CvMemStorage* storage = NULL; 
static CvHaarClassifierCascade* cascade = NULL;

static CvHaarClassifierCascade* cascade_left = NULL;
static CvHaarClassifierCascade* cascade_right = NULL;
static CvHaarClassifierCascade* cascade_eyesglasses = NULL;
static CvHaarClassifierCascade* cascade_eyes = NULL;
static CvHaarClassifierCascade* cascade_nose = NULL;






//const char* cascade_name = "haarcascade_frontalface_alt2.xml"; 
//const char* cascade_name = "haarcascade_frontalface_alt2.xml";
static char* cascade_name = "haarcascade_frontalface_alt_tree.xml";
static char* cascade_left_name = "haarcascade_lefteye_2splits.xml";
static char* cascade_right_name = "haarcascade_righteye_2splits.xml";
//const char* cascade_left_name = "haarcascade_mcs_lefteye.xml";
//const char* cascade_right_name = "haarcascade_mcs_righteye.xml";
//haarcascade_mcs_righteye.xml
//haarcascade_mcs_lefteye.xml
static char* cascade_eyesglasses_name = "haarcascade_eye_tree_eyeglasses.xml";
static char* cascade_eyes_name = "haarcascade_eye.xml";
static char* cascade_nose_name = "haarcascade_mcs_nose.xml";
//const char* cascade_left_name = "haarcascade_eye.xml";
//const char* cascade_right_name = "haarcascade_eye_tree_eyeglasses.xml";
//const char* cascade_right_name = "haarcascade_eye.xml";
//const char* cascade_left_name = "haarcascade_eye.xml";
///*    "haarcascade_profileface.xml";*/





int main( int argc, char** argv )
{

	cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, NULL, NULL, NULL ); 
	cascade_left = (CvHaarClassifierCascade*)cvLoad( cascade_left_name, NULL, NULL, NULL );
	cascade_right = (CvHaarClassifierCascade*)cvLoad( cascade_right_name, NULL, NULL, NULL ); 
	//cascade_eyesglasses = (CvHaarClassifierCascade*)cvLoad( cascade_eyesglasses_name, NULL, NULL, NULL ); 
	//cascade_eyes = (CvHaarClassifierCascade*)cvLoad( cascade_eyes_name, NULL, NULL, NULL ); 
	cascade_nose = (CvHaarClassifierCascade*)cvLoad( cascade_nose_name, NULL, NULL, NULL ); 
	if( !cascade ) 
	{ 
		fprintf( stderr, "ERROR: Could not load classifier cascade\n" ); 
		return -1; 
	} 
	if( !cascade_left ) 
	{ 
		fprintf( stderr, "ERROR: Could not load classifier cascade_left\n" ); 
		return -1; 
	} 
	if( !cascade_right ) 
	{ 
		fprintf( stderr, "ERROR: Could not load classifier cascade_right\n" ); 
		return -1; 
	} 
	//if( !cascade_eyesglasses ) 
	//{ 
	//	fprintf( stderr, "ERROR: Could not load classifier cascade_eyesglasses\n" ); 
	//	return -1; 
	//} 
	//if( !cascade_eyes ) 
	//{ 
	//	fprintf( stderr, "ERROR: Could not load classifier cascade_eyes\n" ); 
	//	return -1; 
	//}
	if( !cascade_nose ) 
	{ 
		fprintf( stderr, "ERROR: Could not load classifier cascade_nose\n" ); 
		return -1; 
	}
	storage = cvCreateMemStorage(0); 
	IplImage* pFrame = NULL; 
	CvCapture* pCapture = NULL;

	int nFrmNum = 0;

	

	
	//////////////////////////////////////////////////////////////////////////
	//  [10/24/2013 yy] block start
	CvRect faceRect;
	faceRect.x=10;
	faceRect.y=10;
	faceRect.height=10;
	faceRect.width=10;
	
	if( !(pCapture = cvCaptureFromCAM(-1)))
	{
		fprintf(stderr, "Can not open camera.\n");
		return -2;
	}
	//if(argc == 2)
	//	if( !(pCapture = cvCaptureFromFile(argv[1])))
	//	{
	//		fprintf(stderr, "Can not open video file %s\n", argv[1]);
	//		return -2;
	//	}



	while(pFrame = cvQueryFrame( pCapture ))
	{
		nFrmNum++;
		 
		detect_and_draw( pFrame,&faceRect); 
	
		if( cvWaitKey(2) >= 0 )
			break;
	}

	cvDestroyWindow("result");

	cvReleaseCapture(&pCapture);

	return 0;
}


void detect_and_draw(IplImage* img,CvRect * faceRect) 
{ 
    double scale=1.2; 
    static CvScalar colors[] = 
	{ 
        {{0,0,255}},{{0,128,255}},{{0,255,255}},{{0,255,0}}, 
        {{255,128,0}},{{255,255,0}},{{255,0,0}},{{255,0,255}} 
    };//Just some pretty colors to draw with

    //Image Preparation 
    // 
    IplImage* gray = cvCreateImage(cvSize(img->width,img->height),8,1); 
    IplImage* small_img=cvCreateImage(cvSize(cvRound(img->width/scale),cvRound(img->height/scale)),8,1); 
    cvCvtColor(img,gray, CV_BGR2GRAY); 
    cvResize(gray, small_img, CV_INTER_LINEAR);
	//cvShowImage("small_img1",small_img);
	//cvWaitKey(0); 

    cvEqualizeHist(small_img,small_img); //直方图均衡
	//cvShowImage("small_img2",small_img);
	//cvWaitKey(0);

    //Detect objects if any 
    // 
	vector <CvRect> faceRectarr;
	objectDetectCV(faceRectarr,small_img,storage,cascade,30);
	for (int i=0;i<faceRectarr.size();i++)
	{
		  cvRectangle(img, cvPoint(faceRectarr[i].x*scale,faceRectarr[i].y*scale), cvPoint((faceRectarr[i].x+faceRectarr[i].width)*scale,(faceRectarr[i].y+faceRectarr[i].height)*scale), colors[i%8]);
		  if (i==0)
		  {
			  faceRect->x=faceRectarr[i].x*scale;
			  faceRect->y=faceRectarr[i].y*scale;
			  faceRect->width=faceRectarr[i].width*scale;
			  faceRect->height=faceRectarr[i].height*scale;

		  }
	}

	IplImage* face_img=cvCreateImage(cvSize(cvRound(faceRect->width),cvRound(faceRect->height)),8,1); 
	cvSetImageROI(gray,*faceRect);
	// 创建子图像
	cvCopy(gray,face_img);
	cvResetImageROI(gray);
	cvEqualizeHist(face_img,face_img); //直方图均衡

	CvRect lefteyeRect;
	CvRect righteyeRect;
	
	vector <CvPoint> eyespoints;
	vector <CvPoint> nosepoints; 
	
	vector<CvRect> lefteyeRectarr;
	objectDetectCV(lefteyeRectarr,face_img,storage,cascade_left,10);
	for (int i=0;i<lefteyeRectarr.size();i++)
	{
		CvPoint tempeye;
		tempeye.x=faceRect->x+lefteyeRectarr[i].x+(lefteyeRectarr[i].width)/2;
		tempeye.y=faceRect->y+lefteyeRectarr[i].y+(lefteyeRectarr[i].height)/2;
		eyespoints.push_back(tempeye);
	}

	vector<CvRect> righteyeRectarr;
	objectDetectCV(righteyeRectarr,face_img,storage,cascade_right,10);
	for (int i=0;i<righteyeRectarr.size();i++)
	{
		CvPoint tempeye;
		tempeye.x=faceRect->x+righteyeRectarr[i].x+(righteyeRectarr[i].width)/2;
		tempeye.y=faceRect->y+righteyeRectarr[i].y+(righteyeRectarr[i].height)/2;
		eyespoints.push_back(tempeye);
	}

	vector<CvRect> noseRectarr;
	objectDetectCV(noseRectarr,face_img,storage,cascade_nose,10);
	for (int i=0;i<noseRectarr.size();i++)
	{
		CvPoint tempnose;
		tempnose.x=faceRect->x+noseRectarr[i].x+(noseRectarr[i].width)/2;
		tempnose.y=faceRect->y+noseRectarr[i].y+(noseRectarr[i].height)/2;
		nosepoints.push_back(tempnose);
	}

	static int eyeslables[1024] = {0};
	CvPoint cluster1,cluster2;

	if (!eyespoints.empty())
	{
		kMean2ClusterCV(eyespoints,eyeslables,&cluster1,&cluster2);
	
		for (int i=0;i < eyespoints.size();i++)
		{
	
			if (eyeslables[i]==1)
			{
				//cvCircle(img,cvPoint(eyespoints[i].x,eyespoints[i].y),1,CV_RGB(255,255,255),2);
			}
			else if(eyeslables[i]==-1)
			{
				//cvCircle(img,cvPoint(eyespoints[i].x,eyespoints[i].y),1,CV_RGB(0,255,255),2);
			}
		}
	//	if (cluster1.x>0&&cluster1.y>0&&cluster2.x>0&&cluster2.y>0&&tip.x>0&&tip.y>0)
	//	{
	//		if ((cluster1.x<tip.x&&cluster2.x>tip.x)||(cluster1.x>tip.x&&cluster2.x<tip.x))
		if (cluster1.x>0&&cluster1.y>0&&cluster2.x>0&&cluster2.y>0)//&&tip.x>0&&tip.y>0
		{
			vector<CvPoint> nosepointscv;
			for (int i=0;i<nosepoints.size();i++)
			{
				CvPoint temp;
				temp.x=nosepoints[i].x;
				temp.y = nosepoints[i].y;
				nosepointscv.push_back(temp);
			}
			alignFace(cvPoint(cluster1.x,cluster1.y),cvPoint(cluster2.x,cluster2.y),nosepointscv,faceRect,img,face_img);
		}

	}
	

//	cvShowImage("face_img",face_img);
    cvShowImage( "result", img );
	//cvShowImage("gray",gray);
    cvReleaseImage(&gray); 
    cvReleaseImage(&small_img);
	cvReleaseImage(&face_img);

}